package org.hibernate.cfg.reveng;

import java.util.Properties;

import org.hibernate.tool.hbm2x.StringUtils;

/**
 * 反转引擎配置
 * 
 * @author iPan
 * @version 2013-12-7
 */
public class ReverseEngineeringSettings {
	private static final String BUILDER_IMPORT_TYPE = "hibernatetools.builder.importType";
	private static final String BUILDER_ENABLE = "hibernatetools.builder.enable";
	private static final String IGNORE_PREFIX = "hibernatetools.ignorePrefix";
	private static final String JAVA_AUTHOR = "hibernatetools.javaAuthor";
	private static final String JAVA_FORMAT = "hibernatetools.javaFormat";
	public static final String REVERSE_VIEW = "hibernatetools.reverseView";
	public static final String META_DATA_DIALECT = "hibernatetools.metaDataDialect";
	public static final String EXPORT_DIR = "hibernatetools.exportDir";
	public static final String DETECT_ONE_TO_ONE = "hibernatetools.detectOneToOne";
	public static final String DETECT_MANY_TO_MANY = "hibernatetools.detectManyToMany";
	public static final String CREATE_MANY_TO_ONE_FOR_FOREIGN_KEY = "hibernatetools.createManyToOneForForeignKey";
	public static final String CREATE_COLLECTION_FOR_FOREIGN_KEY = "hibernatetools.createCollectionForForeignKey";
	public static final String DETECT_OPTIMISTIC_LOCK = "hibernatetools.detectOptimisticLock";
	public static final String DEFAULT_PACKAGE_NAME = "hibernatetools.defaultPackageName";

	/** 引用：反转引擎策略 */
	final ReverseEngineeringStrategy rootStrategy;
	
	/** 默认实体所在包路径 */
	private String defaultPackageName = "";
	
	/** 外键是否生成乐观锁 */
	private boolean detectOptimisticLock = true;
	
	/** 外键是否创建集合 */
	private boolean createCollectionForForeignKey = true; // OneToOne, OneToMany的One端是一个集合，但是此时Mandy端还没被解析出来；所以，通常会设false；
														// 这里设true，是在JDBCBinder中做了处理了，默认泛型类型为Object；
	
	/** 外键是否生成ManyToOne */
	private boolean createManyToOneForForeignKey = true;
	
	/** 外键是否生成ManyToMany */
	private boolean detectManyToMany = true;
	
	/** 外键是否生成OneToOne */
	private boolean detectOneToOne = true;
	
	/** 文件输出目录 */
	private String exportDir = null;
	
	/** 反转引擎方言 */
	private String metadatadialect = null;
	
	/** 是否反转视图 */
	private boolean reverseView = false;
	
	/** 是否格式化Java代码 */
	private boolean javaFormat = true;
	
	/** 生成@author注释 */
	private String javaAuthor = System.getProperty("user.name");
	
	/** 生成实体类需要忽视的前缀 */
	private String[] ignorePrefix = new String[0];
	
	/** 是否支持iPan_Builder */
	private boolean builderEnable = false;
	/** 使用iPan_Builder时要导入的类（逗号分隔） */
	private String[] importType = new String[0];
	
	public ReverseEngineeringSettings(ReverseEngineeringStrategy rootStrategy) {
		this.rootStrategy = rootStrategy;
	}

	public ReverseEngineeringSettings setDefaultPackageName(String defaultPackageName) {
		if (defaultPackageName == null) {
			this.defaultPackageName = "";
		} else {
			this.defaultPackageName = defaultPackageName.trim();
		}
		return this;
	}

	/** return the default packageName. Never null, at least the empty string */
	public String getDefaultPackageName() {
		return defaultPackageName;
	}

	/**
	 * If true, reverse engineering strategy will try and autodetect columns for
	 * optimistc locking, e.g. VERSION and TIMESTAMP
	 */
	public boolean getDetectOptimsticLock() {
		return detectOptimisticLock;
	}

	public ReverseEngineeringSettings setDetectOptimisticLock(boolean optimisticLockSupportEnabled) {
		this.detectOptimisticLock = optimisticLockSupportEnabled;
		return this;
	}

	/** if true, a collection will be mapped for each foreignkey */
	public boolean createCollectionForForeignKey() {
		return createCollectionForForeignKey;
	}

	public ReverseEngineeringSettings setCreateCollectionForForeignKey(boolean createCollectionForForeignKey) {
		this.createCollectionForForeignKey = createCollectionForForeignKey;
		return this;
	}

	/**
	 * if true, a many-to-one association will be created for each foreignkey
	 * found
	 */
	public boolean createManyToOneForForeignKey() {
		return createManyToOneForForeignKey;
	}

	public ReverseEngineeringSettings setCreateManyToOneForForeignKey(boolean createManyToOneForForeignKey) {
		this.createManyToOneForForeignKey = createManyToOneForForeignKey;
		return this;
	}

	public ReverseEngineeringSettings setDetectManyToMany(boolean b) {
		this.detectManyToMany = b;
		return this;
	}

	public boolean getDetectManyToMany() {
		return detectManyToMany;
	}

	public ReverseEngineeringSettings setDetectOneToOne(boolean b) {
		this.detectOneToOne = b;
		return this;
	}

	public boolean getDetectOneToOne() {
		return detectOneToOne;
	}

	/**
	 * return the top/root strategy. Allows a lower strategy to ask another
	 * question. Be aware of possible recursive loops; e.g. do not call the
	 * root.tableToClassName in tableToClassName of a custom
	 * reversengineeringstrategy.
	 */
	public ReverseEngineeringStrategy getRootStrategy() {
		return rootStrategy;
	}
	
	public String getExportDir() {
		return exportDir;
	}

	public void setExportDir(String exportDir) {
		this.exportDir = exportDir;
	}

	public String getMetadatadialect() {
		return metadatadialect;
	}

	public void setMetadatadialect(String metadatadialect) {
		this.metadatadialect = metadatadialect;
	}
	
	public boolean isReverseView() {
		return reverseView;
	}

	public void setReverseView(boolean reverseView) {
		this.reverseView = reverseView;
	}
	
	public boolean isJavaFormat() {
		return javaFormat;
	}

	public void setJavaFormat(boolean javaFormat) {
		this.javaFormat = javaFormat;
	}
	
	public String getJavaAuthor() {
		return javaAuthor;
	}

	public void setJavaAuthor(String javaAuthor) {
		this.javaAuthor = javaAuthor;
	}
	
	public String[] getIgnorePrefix() {
		return ignorePrefix;
	}

	public void setIgnorePrefix(String[] ignorePrefix) {
		this.ignorePrefix = ignorePrefix;
	}
	
	public boolean isBuilderEnable() {
		return builderEnable;
	}

	public void setBuilderEnable(boolean builderEnable) {
		this.builderEnable = builderEnable;
	}

	public String[] getImportType() {
		return importType;
	}

	public void setImportType(String[] importType) {
		this.importType = importType;
	}

	/**
	 * 加载配置信息
	 */
	public ReverseEngineeringSettings loadByProperties(Properties properties) {
		if (properties == null) {
			return this;
		}
		
		if (StringUtils.isNotEmpty(properties.getProperty(DEFAULT_PACKAGE_NAME))) {
			this.setDefaultPackageName(properties.getProperty(DEFAULT_PACKAGE_NAME));
		}
		if (properties.getProperty(DETECT_OPTIMISTIC_LOCK) != null) {
			this.setDetectOptimisticLock(Boolean.parseBoolean(properties.getProperty(DETECT_OPTIMISTIC_LOCK)));
		}
		if (StringUtils.isNotEmpty(properties.getProperty(CREATE_COLLECTION_FOR_FOREIGN_KEY))) {
			this.setCreateCollectionForForeignKey(Boolean.parseBoolean(properties.getProperty(CREATE_COLLECTION_FOR_FOREIGN_KEY)));
		}
		if (StringUtils.isNotEmpty(properties.getProperty(CREATE_MANY_TO_ONE_FOR_FOREIGN_KEY))) {
			this.setCreateManyToOneForForeignKey(Boolean.parseBoolean(properties.getProperty(CREATE_MANY_TO_ONE_FOR_FOREIGN_KEY)));
		}
		if (StringUtils.isNotEmpty(properties.getProperty(DETECT_MANY_TO_MANY))) {
			this.setDetectManyToMany(Boolean.parseBoolean(properties.getProperty(DETECT_MANY_TO_MANY)));
		}
		if (StringUtils.isNotEmpty(properties.getProperty(DETECT_ONE_TO_ONE))) {
			this.setDetectOneToOne(Boolean.parseBoolean(properties.getProperty(DETECT_ONE_TO_ONE)));
		}
		if (StringUtils.isNotEmpty(properties.getProperty(EXPORT_DIR))) {
			this.setExportDir(properties.getProperty(EXPORT_DIR));
		}
		if (StringUtils.isNotEmpty(properties.getProperty(META_DATA_DIALECT))) {
			this.setMetadatadialect(properties.getProperty(META_DATA_DIALECT));
		}
		if (StringUtils.isNotEmpty(properties.getProperty(REVERSE_VIEW))) {
			this.setReverseView(Boolean.parseBoolean(properties.getProperty(REVERSE_VIEW)));
		}
		if (StringUtils.isNotEmpty(properties.getProperty(JAVA_FORMAT))) {
			this.setJavaFormat(Boolean.parseBoolean(properties.getProperty(JAVA_FORMAT)));
		}
		if (StringUtils.isNotEmpty(properties.getProperty(JAVA_AUTHOR))) {
			this.setJavaAuthor(properties.getProperty(JAVA_AUTHOR));
		}
		if (StringUtils.isNotEmpty(properties.getProperty(IGNORE_PREFIX))) {
			String[] prefix = properties.getProperty(IGNORE_PREFIX).replace(" ", "").split(",");
			this.setIgnorePrefix(prefix);
			rootStrategy.setIgnorePrefix(prefix); // 加载配置的时候同时修改默认反转策略的值
		}
		if (StringUtils.isNotEmpty(properties.getProperty(BUILDER_ENABLE))) {
			this.setBuilderEnable(Boolean.parseBoolean(properties.getProperty(BUILDER_ENABLE)));
		}
		if (StringUtils.isNotEmpty(properties.getProperty(BUILDER_IMPORT_TYPE))) {
			String[] types = properties.getProperty(BUILDER_IMPORT_TYPE).replace(" ", "").split(",");
			this.setImportType(types);
		}
		return this;
	}
	
}
